#include "stdafx.h"

StaticMesh::StaticMesh(const D3DXVECTOR3& position, const D3DXVECTOR3& size) :
	IDrawable(position, size, nullptr, nullptr),
	mIndexBuffer(nullptr)
{
}


StaticMesh::~StaticMesh(void)
{
	if(mVertexBuffer != nullptr)
		mVertexBuffer->Release();

	if(mIndexBuffer != nullptr)
		mIndexBuffer->Release();

	if(mTexture != nullptr)
		mTexture->Release();
}

void init_light(void)
{
	D3DLIGHT9 light;    // create the light struct
	D3DMATERIAL9 material;

	const float x = 0.5f;

	ZeroMemory(&light, sizeof(light));    // clear out the light struct for use
	light.Position = D3DXVECTOR3(10, 15, 5);
	light.Type = D3DLIGHT_DIRECTIONAL;    // make the light type 'directional light'
	light.Diffuse = D3DXCOLOR(x, x, x, 1.0f);    // set the light's color
	light.Ambient = D3DXCOLOR(x, x, x, 1.0f);    // set the light's color
	light.Specular = D3DXCOLOR(x, x, x, 1.0f);    // set the light's color
	light.Direction = D3DXVECTOR3(10, -10, 0);
	light.Range = 10000;

	globals::d3dDevice->SetLight(0, &light);    // send the light struct properties to light #0
	globals::d3dDevice->LightEnable(0, TRUE);    // turn on light #0

	ZeroMemory(&material, sizeof(D3DMATERIAL9));    // clear out the struct for use
	material.Diffuse = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);    // set diffuse color to white
	material.Ambient = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);    // set ambient color to white

	globals::d3dDevice->SetMaterial(&material);    // set the globably-used material to &material
}


void StaticMesh::fromObjFile(const std::string& file, int firstIndex)
{
	//init_light();
	std::vector<Vertex> vertices;
	std::vector<short> indices;

	std::ifstream inFile(file);
	if(inFile.is_open())
	{
		std::string line;
		int tex = 0;
		while(inFile.good())
		{
			std::stringstream ss;
			getline(inFile, line);
			if(line[0] == 'v')
			{
				if(line[1] == 'n')
				{
				}
				else
				{
					Vertex vertex;
					/*
					vertex.nx = 0;
					vertex.ny = 1;
					vertex.nz = 0;

					if(tex == 0)
					{
						vertex.tv = 0;
						vertex.tu = 0;
					}
					if(tex == 1)
					{
						vertex.tv = 0;
						vertex.tu = 1;
					}
					if(tex == 2)
					{
						vertex.tv = 1;
						vertex.tu = 1;
						tex = 0;
					}*/

					++tex;

					ss << line.substr(2, -1);
					ss >> vertex.x;
					ss >> vertex.y;
					ss >> vertex.z;
					vertex.x += mSize.x * mPosition.x;
					vertex.y += mSize.y * mPosition.y;
					vertex.z += mSize.z * mPosition.z;
					std::cout << vertex.x << " " << vertex.y << " " << vertex.z << std::endl;
					vertices.push_back(vertex);
				}
			}
			else if(line[0] == 'f')
			{
				short a;
				std::replace(line.begin(), line.end(), '/', ' ');
				ss << line.substr(2, -1);
				for(int i = 0; i < 3; ++i)
				{
					int normal;
					ss >> a;
					ss >> normal;
					a -= firstIndex; //indices start from 0
					indices.push_back(a);
					std::cout << a << " ";
				}
				std::cout << std::endl;
			}
		}

		auto size = vertices.size() * sizeof(Vertex);
		mNumVertices = vertices.size();

		globals::d3dDevice->CreateVertexBuffer(size, D3DUSAGE_WRITEONLY, Vertex::FVF_Flags, D3DPOOL_DEFAULT, &mVertexBuffer, nullptr);
		void *pVertices;
		mVertexBuffer->Lock( 0, 0, (void**)&pVertices, 0 );

		memcpy( pVertices, &*vertices.begin(), size );
		mVertexBuffer->Unlock();

		size = indices.size() * sizeof(short);
		mNumIndices = indices.size() / 3;

		globals::d3dDevice->CreateIndexBuffer(size, 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &mIndexBuffer, nullptr);
		void* pIndices;
		mIndexBuffer->Lock(0, 0, (void**)&pIndices, 0);

		memcpy(pIndices, &*indices.begin(), size);
		mIndexBuffer->Unlock();
	}
}


void StaticMesh::render()
{
	globals::d3dDevice->SetStreamSource(0, mVertexBuffer, 0, sizeof(Vertex));
	globals::d3dDevice->SetIndices(mIndexBuffer);
	//globals::d3dDevice->SetTexture( 0, mTexture );

	//globals::d3dDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
	globals::d3dDevice->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(50, 50, 50));

	globals::d3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, mNumVertices, 0, mNumIndices);
}


void StaticMesh::setTexture(const std::string& file)
{
	if(mTexture != nullptr)
		mTexture->Release();

	D3DXCreateTextureFromFile(globals::d3dDevice, file.c_str(), &mTexture);
}


void StaticMesh::setPosition(const D3DXVECTOR3& position)
{
	mPosition = position;
}


D3DXVECTOR3 StaticMesh::getPosition()
{
	return mPosition;
}


std::string mfakeGet()
{
	return nullptr;
}


void StaticMesh::toLua()
{
	using luabind::def;
	using luabind::class_;

	luabind::module(lua::State())
		[
			class_<StaticMesh>("StaticMesh").
			def(luabind::constructor<const D3DXVECTOR3&, const D3DXVECTOR3&>()).
			def("render", &StaticMesh::render).
			def("fromObjFile", &StaticMesh::fromObjFile).
			property("position", &StaticMesh::getPosition, &StaticMesh::setPosition).
			property("texture", &mfakeGet, &StaticMesh::setTexture)
		];
}